﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace Pixer
{
    public class Canvas : PictureBox
    {
        //画板中的图形列表
        private List<Shape> shapes;

        private Mode mode;
        /// <summary>
        /// 当前的绘图模式
        /// </summary>
        public Mode Mode
        {
            get { return mode; }
            set { mode = value; }
        }

        private Point startPoint;
        /// <summary>
        /// 起点，鼠标最后一次按下时的坐标
        /// </summary>
        public Point StartPoint
        {
            get { return startPoint; }
            set { startPoint = value; }
        }

        private Point currentPoint;
        /// <summary>
        /// 当前点，鼠标移动时的当前坐标
        /// </summary>
        public Point CurrentPoint
        {
            get { return currentPoint; }
            set { currentPoint = value; }
        }

        private Point endPoint;
        /// <summary>
        /// 终点，鼠标最后一次释放时的坐标
        /// </summary>
        public Point EndPoint
        {
            get { return endPoint; }
            set { endPoint = value; }
        }

        
        private bool mouseStateChanged;
        /// <summary>
        /// 鼠标状态改变
        /// </summary>
        public bool MouseStateChanged
        {
            get { return mouseStateChanged; }
            set { mouseStateChanged = value; }
        }

        private int mouseState;
        /// <summary>
        /// 鼠标状态，0为鼠标释放状态，1为鼠标按下状态,2为双击状态
        /// </summary>
        public int MouseState   
        {
            get { return mouseState; }
            set { mouseState = value; }
        }

        private List<Point> points;

        public List<Point> Points
        {
            get { return points; }
            set { points = value; }
        }

        private Color lineColor;

        public Color LineColor
        {
            get { return lineColor; }
            set { lineColor = value; }
        }
        private Color fillColor;

        public Color FillColor
        {
            get { return fillColor; }
            set { fillColor = value; }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        public Canvas()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);   //   禁止擦除背景.   
            SetStyle(ControlStyles.DoubleBuffer, true);   //   双缓冲   
            shapes = new List<Shape>();
            startPoint = new Point(-1, -1);
            points = new List<Point>();
            points.Add(new Point(0, 0));
            fillColor = Color.White;
            lineColor = Color.Black;

           
        }
        

        /// <summary>
        /// 处理重绘事件.！！主要！！
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;
        
           // paintShapes(g);

            switch (mode)
            {
                case Mode.PIXEL: paintPixel(g); break;
                case Mode.LZSB: paintLzsb(g);break;
                case Mode.LINE: paintLine(g);break;
                case Mode.CIRCLE: paintCircle(g); break;
                case Mode.ELLIPSE: paintEllipse(g); break;
                case Mode.FILL: fill(g); break;
                case Mode.CURVE: paintCurve(g); break;
                case Mode.RECTANGLE: paintRectangle(g); break;
            }          
        }

        /// <summary>
        /// 画矩形
        /// </summary>
        /// <param name="g"></param>
        private void paintRectangle(Graphics g)
        {
            if (MouseState == 1)
            {
                Rectangle rect = new Rectangle();
                int x = Math.Min(currentPoint.X , startPoint.X);
                int y = Math.Min(currentPoint.Y , startPoint.Y);
                rect.Position = new Point(x, y);
                rect.Width = Math.Abs(currentPoint.X - startPoint.X);
                rect.Height = Math.Abs(currentPoint.Y - startPoint.Y);
                rect.paint(g);

            }
            else if (MouseState == 0 && mouseStateChanged)
            {
                mouseStateChanged = false;
                Rectangle rect = new Rectangle();
                rect.Position = startPoint;
                rect.Width = endPoint.X - startPoint.X;
                rect.Height = endPoint.Y - startPoint.Y;
                shapes.Add(rect);
                rect.LineColor = LineColor;
                rect.paint((Bitmap)this.Image);
                startPoint = new Point(-1, -1);
                this.Update();
            }
        }

        /// <summary>
        /// 画曲线
        /// </summary>
        /// <param name="g"></param>
        private void paintCurve(Graphics g)
        {
            if (startPoint.X != -1 && startPoint.Y != -1)
            {
                if (mouseState == 1 && mouseStateChanged)
                {
                    mouseStateChanged = false;
                    this.points.Add(startPoint);
                    Curve c = new Curve();                 
                    c.Points = this.points;
                    c.paint(g);
                }
                else if (mouseState == 0 || mouseState == 1 && !mouseStateChanged)
                {
 
                    Curve c = new Curve();
                    foreach (Point p in points)
                        c.Points.Add(p);
                    c.Points.Add(currentPoint);
                    c.Points.Add(currentPoint);
                    c.paint(g);
                }
                else if (MouseState == 2)
                {
                    points.Add(endPoint);
                    Curve c = new Curve();
                    c.LineColor = LineColor;
                    c.Points = this.points;
                    shapes.Add(c);
                    c.paint((Bitmap)this.Image);
                    this.points.Clear();
                    this.points.Add(new Point(0,0));
                    this.Update();
                }
            }
        }

        private void paintPixel(Graphics g)
        {
            if (startPoint.X != -1 && startPoint.Y != -1 && MouseState == 0 && mouseStateChanged)
            {
                mouseStateChanged = !mouseStateChanged;
                Pixel p = new Pixel();
                p.LineColor = LineColor;
                p.Point = currentPoint;
                p.paint((Bitmap)this.Image);
                this.Update();
            }
        }

        //保持图像
        private void fill(Graphics g)
        {
            if (mouseState == 1 && mouseStateChanged)
            {
                mouseStateChanged = false;
                Fill f = new Fill();
                f.Position = startPoint;
                f.FillColor = fillColor;
                f.paint((Bitmap)this.Image);

            }
        }

        /// <summary>
        /// 绘制椭圆
        /// </summary>
        /// <param name="g"></param>
        private void paintEllipse(Graphics g)
        {
            if (startPoint.X != -1 && startPoint.Y != -1)
            {
                if (MouseState == 1)
                {
                    Ellipse c = new Ellipse();
                    c.Center = getMiddlePoint(startPoint,currentPoint);
                    c.Width = Math.Abs(startPoint.X - currentPoint.X);
                    c.Height = Math.Abs(startPoint.Y - currentPoint.Y);
                    c.paint(g);
                }
                else if (MouseState == 0 && mouseStateChanged)
                {
                    mouseStateChanged = false;
                    Ellipse c = new Ellipse();
                    c.Center = getMiddlePoint(startPoint, endPoint);
                    c.Width = Math.Abs(startPoint.X - endPoint.X);
                    c.Height = Math.Abs(startPoint.Y - endPoint.Y);
                    shapes.Add(c);
                    c.LineColor = LineColor;
                    c.paint((Bitmap)this.Image);
                    startPoint = new Point(-1, -1);
                    this.Update();
                }
            }
        }

        /// <summary>
        /// 绘制圆
        /// </summary>
        /// <param name="g"></param>
        private void paintCircle(Graphics g)
        {
            if (startPoint.X != -1 && startPoint.Y != -1)
            {
                if (MouseState == 1)
                {
                    Circle c = new Circle();
                    c.Center = getMiddlePoint(startPoint, currentPoint);
                    c.Radius = distance(startPoint, currentPoint)/2;
                    c.paint(g);
                }
                else if (MouseState == 0 && mouseStateChanged)
                {
                    mouseStateChanged = false;
                    Circle c = new Circle();
                    c.Center = getMiddlePoint(startPoint, endPoint);
                    c.Radius = distance(startPoint, endPoint)/2;
                    c.LineColor = LineColor;
                    shapes.Add(c);
                    c.paint((Bitmap)this.Image);
                    startPoint = new Point(-1, -1);
                    this.Update();
                }
            }
        }

        /// <summary>
        /// 绘制直线
        /// </summary>
        /// <param name="g"></param>
        private void paintLine(Graphics g)
        {
            if (startPoint.X != -1 && startPoint.Y != -1)
            {
                if (MouseState == 1)
                {
                    Line l = new Line();
                    l.StartPoint = startPoint;
                    l.EndPoint = currentPoint;
                    l.paint(g);
                }
                else if (MouseState == 0 && mouseStateChanged)
                {
                    mouseStateChanged = false;
                    Line l = new Line();
                    l.StartPoint = startPoint;
                    l.EndPoint = currentPoint;
                    l.LineColor = LineColor;
                    shapes.Add(l);
                    l.paint((Bitmap)this.Image);
                    startPoint = new Point(-1, -1);
                    this.Update();
                }
            }
        }

        /// <summary>
        /// 绘制兰州烧饼
        /// </summary>
        /// <param name="g"></param>
        private void paintLzsb(Graphics g)
        {
            Pixel pixel = new Pixel();
            pixel.Point = startPoint;
            pixel.paint(g);
            startPoint = new Point(-1, -1);
        }

        /// <summary>
        /// 画出保存的图形
        /// </summary>
        /// <param name="g"></param>
        protected void paintShapes(Graphics g)
        {
            foreach (Shape shape in shapes)
            {
                shape.paint(g);
            }
        }

        /// <summary>
        /// 计算两点间距离
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        protected int distance(Point a, Point b)
        {
            return (int)Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
        }

        protected Point getMiddlePoint(Point a, Point b)
        {
            return new Point((a.X+b.X)/2,(a.Y+b.Y)/2);
        }
    }
}
